#include "rpc_server.hpp"

#include <functional>

#include <google/protobuf/descriptor.h>
#include <google/protobuf/service.h>

#include "../base/logger.h"
#include "rpc_channel.hpp"

namespace easyasio
{
namespace net
{

RpcServer::RpcServer(const std::string& address, const std::string& port, std::size_t io_service_pool_size)
    : server_(address, port, io_service_pool_size)
{
    server_.setConnectionCallback(std::bind(&RpcServer::onConnection, this, std::placeholders::_1));
    //   server_.setMessageCallback(
    //       boost::bind(&RpcServer::onMessage, this, _1, _2, _3));
}

void RpcServer::registerService(google::protobuf::Service* service)
{
    const google::protobuf::ServiceDescriptor* desc = service->GetDescriptor();
    services_[desc->name()] = service;
}

void RpcServer::start()
{
    server_.run();
}

void RpcServer::onConnection(const TcpConnectionPtr& conn)
{
    LOG_INFO("RpcServer - {} -> {} is {}", conn->socket().remote_endpoint().address().to_string(), 
        conn->socket().remote_endpoint().port(), conn->connected() ? "UP" : "DOWN");

    if (conn->connected())
    {
        RpcChannelPtr channel(new RpcChannel(conn));
        channel->setServices(&services_);
        conn->setMessageCallback(
            std::bind(&RpcChannel::onMessage, channel, std::placeholders::_1, std::placeholders::_2));
        conn->setContext(channel);
    }
    else
    {
        conn->setContext(RpcChannelPtr());
        // FIXME:
    }
}

// void RpcServer::onMessage(const TcpConnectionPtr& conn,
//                           Buffer* buf,
//                           Timestamp time)
// {
//   RpcChannelPtr& channel = boost::any_cast<RpcChannelPtr&>(conn->getContext());
//   channel->onMessage(conn, buf, time);
// }

}
}
